001 /* 002 * Copyright (c) 2005 Stephen J. McConnell 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 013 * implied. 014 * 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019 package net.dpml.metro.tools; 020 021 import java.io.File; 022 import java.io.FileOutputStream; 023 import java.io.IOException; 024 025 import net.dpml.tools.tasks.GenericTask; 026 027 import net.dpml.state.State; 028 import net.dpml.state.StateEncoder; 029 030 import org.apache.tools.ant.BuildException; 031 032 /** 033 * Task that handles the creation of an encoded state graph. 034 * 035 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a> 036 * @version 1.1.0 037 */ 038 public class StateTask extends GenericTask 039 { 040 private static final StateEncoder STATE_ENCODER = new StateEncoder(); 041 042 private File m_output; 043 private String m_classname; 044 private StateDataType m_data; 045 046 StateDataType getData() 047 { 048 if( null == m_data ) 049 { 050 m_data = new StateDataType( this, true ); 051 } 052 return m_data; 053 } 054 055 /** 056 * Override the default output destination. 057 * 058 * @param file the overriding destination 059 */ 060 public void setDest( File file ) 061 { 062 m_output = file; 063 } 064 065 /** 066 * Override the class as the colocated destination. 067 * 068 * @param classname the classname of the target component. 069 */ 070 public void setClass( String classname ) 071 { 072 m_classname = classname; 073 } 074 075 /** 076 * Set the state name. 077 * @param name the cname of the state 078 */ 079 public void setName( final String name ) 080 { 081 getData().setName( name ); 082 } 083 084 /** 085 * Mark the state as a terminal state. 086 * @param flag true if this is a terminal state 087 */ 088 public void setTerminal( final boolean flag ) 089 { 090 getData().setTerminal( flag ); 091 } 092 093 /** 094 * Add a substate within the state. 095 * @return the sub-state datatype 096 */ 097 public StateDataType createState() 098 { 099 return getData().createState(); 100 } 101 102 /** 103 * Add an operation within this state. 104 * @return the operation datatype 105 */ 106 public OperationDataType createOperation() 107 { 108 return getData().createOperation(); 109 } 110 111 /** 112 * Add an interface within this state. 113 * @return the interface datatype 114 */ 115 public InterfaceDataType createInterface() 116 { 117 return getData().createInterface(); 118 } 119 120 /** 121 * Add an transition within this state. 122 * @return the operation datatype 123 */ 124 public TransitionDataType createTransition() 125 { 126 return getData().createTransition(); 127 } 128 129 /** 130 * Add an trigger to the state. 131 * @return the trigger datatype 132 */ 133 public TriggerDataType createTrigger() 134 { 135 return getData().createTrigger(); 136 } 137 138 /** 139 * Execute the task. 140 */ 141 public void execute() 142 { 143 File file = getOutputFile(); 144 File parent = file.getParentFile(); 145 if( !parent.exists() ) 146 { 147 parent.mkdirs(); 148 } 149 createGraph( file ); 150 } 151 152 /** 153 * Create an encoded state graph. 154 * @param file the output file 155 */ 156 public void createGraph( File file ) 157 { 158 try 159 { 160 FileOutputStream output = new FileOutputStream( file ); 161 try 162 { 163 State graph = getData().getState(); 164 STATE_ENCODER.export( graph, output ); 165 } 166 catch( Exception e ) 167 { 168 throw new BuildException( "State encoding error.", e ); 169 } 170 finally 171 { 172 try 173 { 174 output.close(); 175 } 176 catch( IOException ioe ) 177 { 178 ioe.printStackTrace(); 179 } 180 } 181 } 182 catch( BuildException e ) 183 { 184 throw e; 185 } 186 catch( Exception e ) 187 { 188 final String error = 189 "Internal error while attempting to build the graph."; 190 throw new BuildException( error, e, getLocation() ); 191 } 192 } 193 194 private File getOutputFile() 195 { 196 if( null != m_output ) 197 { 198 return m_output; 199 } 200 else if( null != m_classname ) 201 { 202 File classes = getContext().getTargetClassesMainDirectory(); 203 String path = m_classname.replace( '.', '/' ); 204 String filename = path + ".xgraph"; 205 return new File( classes, filename ); 206 } 207 else 208 { 209 return getDefaultOutputFile(); 210 } 211 } 212 213 /** 214 * Create and return the part output file. 215 * @return the part output file 216 */ 217 protected File getDefaultOutputFile() 218 { 219 File deliverables = getContext().getTargetDeliverablesDirectory(); 220 String type = State.TYPE; 221 String types = type + "s"; 222 File dir = new File( deliverables, types ); 223 String filename = getContext().getLayoutPath( type ); 224 return new File( dir, filename ); 225 } 226 }